package com.shop.web.context;

import com.shop.jpa.support.QuerySQL;
import com.shop.util.RandomUtil;
import com.shop.web.filter.BodyReaderHttpServletRequestWrapper;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.http.HttpServletRequest;

/**
 * 公共请求参数上下文
 */
@Slf4j
public class WebContext {


    protected static final ThreadLocal<String> TL_REQUEST_ID = new ThreadLocal() {
        public String initialValue() {
            return RandomUtil.randomUUID32();
        }
    };

    protected static final ThreadLocal<Object> TL_PRINCIPAL = new ThreadLocal();

    protected static final ThreadLocal<String> TL_ACCESS_TOKEN = new ThreadLocal();
    protected static final ThreadLocal<String> TL_REQUEST_TIMESTAMP = new ThreadLocal();
    protected static final ThreadLocal<String> TL_REQUEST_IP = new ThreadLocal();
    protected static final ThreadLocal<String> TL_CLIENT_TYPE = new ThreadLocal();
    protected static final ThreadLocal<String> TL_CLIENT_MODEL = new ThreadLocal();
    protected static final ThreadLocal<String> TL_CLIENT_VERSION = new ThreadLocal();
    protected static final ThreadLocal<String> TL_CLIENT_ID = new ThreadLocal();
    protected static final ThreadLocal<String> TL_MER_CODE = new ThreadLocal();

    protected static final ThreadLocal<String> TL_REQUEST_BODY = new ThreadLocal();
    protected static final ThreadLocal<Integer> TL_PAGE_NO = new ThreadLocal();
    protected static final ThreadLocal<Integer> TL_PAGE_SIZE = new ThreadLocal();
    protected static final ThreadLocal<Long> TL_SIGN_ID = new ThreadLocal();


    public static Object getPrincipal() {
        return TL_PRINCIPAL.get();
    }

    public static void setPrincipal(Object principal) {
        TL_PRINCIPAL.set(principal);
    }

    public static String getAccessToken() {
        return TL_ACCESS_TOKEN.get();
    }

    public static void setAccessToken(String accessToken) {
        TL_ACCESS_TOKEN.set(accessToken);
    }

    public static Long getSignId() {
        return TL_SIGN_ID.get();
    }

    public static void setSignId(Long id) {
        TL_SIGN_ID.set(id);
    }

    public static String getMerCode() {
        return TL_MER_CODE.get();
    }

    public static void setMerCode(String merCode) {
        TL_MER_CODE.set(merCode);
    }

    public static String getRequestId() {
        return TL_REQUEST_ID.get();
    }

    public static void setRequestId(String requestId) {
        TL_REQUEST_ID.set(requestId);
    }

    public static String getRequestIp() {
        return TL_REQUEST_IP.get();
    }

    public static void setRequestIp(String requestIp) {
        TL_REQUEST_IP.set(requestIp);
    }

    public static String getRequestTimestamp() {
        return TL_REQUEST_TIMESTAMP.get();
    }

    public static void setRequestTimestamp(String requestTimestamp) {
        TL_REQUEST_TIMESTAMP.set(requestTimestamp);
    }

    public static String getClientType() {
        return TL_CLIENT_TYPE.get();
    }

    public static void setClientType(String clientType) {
        TL_CLIENT_TYPE.set(clientType);
    }

    public static String getClientModel() {
        return TL_CLIENT_MODEL.get();
    }

    public static void setClientModel(String clientModel) {
        TL_CLIENT_MODEL.set(clientModel);
    }

    public static String getClientVersion() {
        return TL_CLIENT_VERSION.get();
    }

    public static void setClientVersion(String clientVersion) {
        TL_CLIENT_VERSION.set(clientVersion);
    }

    public static String getClientId() {
        return TL_CLIENT_ID.get();
    }

    public static void setClientId(String clientId) {
        TL_CLIENT_ID.set(clientId);
    }

    public static Integer getPageNo() {
        return null == TL_PAGE_NO.get() ? QuerySQL.DEFAULT_PAGE_NO : TL_PAGE_NO.get();
    }

    public static void setPageNo(Integer pageNo) {
        TL_PAGE_NO.set(pageNo);
    }

    public static Integer getPageSize() {
        return null == TL_PAGE_SIZE.get() ? QuerySQL.DEFAULT_PAGE_SIZE : TL_PAGE_SIZE.get();
    }

    public static void setPageSize(Integer pageSize) {
        TL_PAGE_SIZE.set(pageSize);
    }

    public static String getRequestBody() {
        return TL_REQUEST_BODY.get();
    }

    public static void setRequestBody(String requestBody) {
        TL_REQUEST_BODY.set(requestBody);
    }

    public static void clearThreadLocals() {
        TL_REQUEST_ID.remove();
        TL_PRINCIPAL.remove();
        TL_ACCESS_TOKEN.remove();
        TL_REQUEST_TIMESTAMP.remove();
        TL_CLIENT_TYPE.remove();
        TL_CLIENT_VERSION.remove();
        TL_CLIENT_ID.remove();
        TL_REQUEST_IP.remove();
        TL_CLIENT_MODEL.remove();
        TL_MER_CODE.remove();
        TL_REQUEST_BODY.remove();
        TL_PAGE_NO.remove();
        TL_PAGE_SIZE.remove();
        TL_SIGN_ID.remove();
    }

    /**
     * 获取 requestBody
     * @param request
     * @return
     */
    public static String requestBody(HttpServletRequest request) {
        if ("application/json".equals(request.getContentType())
                || "application/json;charset=UTF-8".equals(request.getContentType())
                || "application/json; charset=UTF-8".equals(request.getContentType())
                || "application/json;charset=utf-8".equals(request.getContentType())
                || "application/json; charset=utf-8".equals(request.getContentType())
                || "application/json".equals(request.getContentType())
                || "application/x-www-form-urlencoded".equals(request.getContentType())
                || "text/html;charset=utf-8".equals(request.getContentType())) {
            if (request instanceof BodyReaderHttpServletRequestWrapper) {
                BodyReaderHttpServletRequestWrapper bodyRequest =
                        (BodyReaderHttpServletRequestWrapper) request;
                byte[] copyBytes = bodyRequest.getCopy();
                byte[] subBytes = copyBytes;
                try {
                    return new String(subBytes, "UTF-8");
                } catch (Exception e) {
                    log.error("-error-requestBody-", e);
                }
            }
        }

        return null;
    }
}
